package com.broker.starter.service.impl;

import com.broker.starter.constant.MinIOConstants;
import com.broker.starter.exception.MinIOException;
import com.broker.starter.service.MinIOService;
import io.minio.BucketExistsArgs;
import io.minio.DownloadObjectArgs;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import io.minio.http.Method;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

/**
 * @author XXX
 */
public class MinIOServiceImpl implements MinIOService {

    private static Logger log = Logger.getLogger(MinIOServiceImpl.class.getName());

    @Autowired
    private MinioClient minioClient;

    @Override public Optional<String> upload(MultipartFile file, String bucketName, String contentType)
        throws IOException {
        if (Objects.isNull(file)){
            throw new MinIOException("file can't be empty.");
        }
        long partSize = file.getSize();
        if (partSize < MinIOConstants.MIN_SIZE){
            partSize = MinIOConstants.MIN_SIZE;
        }
        return upload(bucketName, file.getOriginalFilename(), contentType, file.getInputStream(), file.getSize(), partSize);
    }

    @Override
    public Optional<String> upload(String bucketName, String objectName, String contentType, InputStream stream, long objectSize,
        long partSize) {
        try {
            if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())){
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            }
            // 上传文件
            minioClient.putObject(PutObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .stream(stream, objectSize, partSize)
                .contentType(contentType)
                .build());

            return getObjUrl(bucketName, objectName);
        } catch (Exception e) {
            log.info(e.getMessage());
        }
        return Optional.empty();
    }

    @Override
    public void download(String bucketName, String objectName, String fileName) {
        try {
            // 下载文件
            minioClient.downloadObject(DownloadObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .filename(fileName)
                .build());
        } catch (Exception e) {
            log.info(e.getMessage());
        }
    }

    @Override
    public void delete(String bucketName, String objectName) {
        try {
            // 删除文件
            minioClient.removeObject(RemoveObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .build());
        } catch (Exception e) {
            log.info(e.getMessage());
        }
    }

    @Override
    public Optional<String> getObjUrl(String bucketName, String objectName) {
        try {
            // 获取存储路径URL
            return Optional.of(minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .method(Method.GET)
                .build()));
        } catch (Exception e) {
            log.info(e.getMessage());
        }
        return Optional.empty();
    }

    @Override
    public Optional<String> getObjUrl(String bucketName, String objectName, int duration, TimeUnit unit) {
        try {
            // 获取存储路径URL 带过期时间
            return Optional.of(minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .expiry(duration, unit)
                .method(Method.GET)
                .build()));
        } catch (Exception e) {
            log.info(e.getMessage());
        }
        return Optional.empty();
    }
}
